home *** CD-ROM | disk | FTP | other *** search
/ NeXT Education Software Sampler 1992 Fall / NeXT Education Software Sampler 1992 Fall.iso / Programming / Source / Adroff2 / Controller.m < prev    next >
Encoding:
Text File  |  1992-07-27  |  10.4 KB  |  371 lines

  1. /*  Controller.m --- Main controller object for the TextLab program.
  2. **  Authors: Bruce Blumberg and Ali Ozer, NeXT Developer Support Group
  3. **    8-14-90 Converted to 2.0 by Randy Nelson, NeXT Developer Training
  4. **    Changed internal strings to external using NXStringTable
  5. **    Removed outlet initializers
  6. **    Removed 0.9 reference to Font Manager
  7. **    9-7-90 Changed new method to use init, externally stored info panel
  8. **
  9. **    You may freely copy, distribute and reuse the code in this example.
  10. **    NeXT disclaims any warranty of any kind, expressed or implied, as to
  11. **    its fitness for any particular use.
  12. */
  13.  
  14. // Controller object is the central object in TextLab.  It manages the
  15. // windows, open/save panels, and menu commands. 
  16.  
  17. #import "Controller.h"
  18. #import "TextView.h"
  19. #import <appkit/Application.h>
  20. #import <objc/typedstream.h>
  21. #import <objc/NXStringTable.h>
  22. #import <appkit/FontManager.h>
  23. #import <appkit/Font.h>
  24.  
  25. @implementation Controller
  26.  
  27. - init
  28. {
  29.   [super init];
  30.   
  31.   // get instances of support objects
  32.   openReq = [OpenPanel new];
  33.   saveReq = [SavePanel new];
  34.   [self make2Windows];
  35.   return self;
  36. }
  37.  
  38.  
  39. - infoPanel:sender
  40. {
  41.     if (infoPanel == nil) {
  42.     [NXApp loadNibSection:"Info.nib" owner:self];
  43.     }
  44.     [infoPanel orderFront:sender];
  45.     return self;
  46. }
  47.  
  48. - showError: (const char *)errorMessage
  49. {
  50.   NXRunAlertPanel(NULL, errorMessage,
  51.             [stringSet valueForStringKey:"OK"], NULL, NULL);
  52.   return self;
  53. }
  54.  
  55. // newTextView: is invoked in response to a new empty window request. It
  56. // creates a new window containing a TextView. Note that we want new windows 
  57. // to be offset from each other by some amount; hence the use of wRect.
  58.  
  59. #define ORIGX 0.0
  60. #define ORIGY 0.0
  61. // static NXRect wRect = {{ORIGX, ORIGY},{450.0,400.0}};
  62. static NXRect sourceRect = {{120.0, 440.0},{800.0,300.0}};
  63. static NXRect diagramRect = {{120.0, 100.0},{800.0,300.0}};
  64.  
  65. - make2Windows
  66. {
  67.     id diagramText;
  68.     id sourceText;
  69.     
  70.     // diagramView = [self newTextView:self];
  71.     diagramView = [[TextView alloc] initFrame:&diagramRect];
  72.     // [[diagramView window] setDelegate:self];
  73.     [[diagramView window] setTitle:"Diagram"];// replace "Untitled"  
  74.     diagramText = [diagramView docView];
  75.     [diagramText setFont:[Font  newFont:"IBMKlone" size:12.0 ]];
  76.     
  77.     [diagramText setDescentLine:0.0];
  78.     [diagramText setLineHeight:36.0];
  79.     [diagramText calcLine];    
  80.   
  81.     // sourceView = [self newTextView:self];
  82.     sourceView = [[TextView alloc] initFrame:&sourceRect];
  83.     [[sourceView window] setDelegate:self];
  84.     [[sourceView window] setTitle:"SourceCode"];  // replace "Untitled"     
  85.  
  86.     sourceText = [sourceView docView];
  87.     [sourceText selectText:self];
  88.     [sourceText setDelegate:self]; // so we will get textDidGetKeys msg.
  89.  
  90.      return self;
  91. }
  92.  
  93. - newTextView:sender
  94. {
  95.     //int i (int i);  /*counter*/
  96.     id newTextView;
  97.     NXOffsetRect(&sourceRect, 100.0, 100.0);
  98.     if (sourceRect.origin.y < 0) {
  99.         sourceRect.origin.y = ORIGY;
  100.     sourceRect.origin.x = ORIGX;
  101.     }
  102.     //for (i=1; i++);
  103.     newTextView = [[TextView alloc] initFrame:&sourceRect];
  104.     [[newTextView window] setDelegate:self];     
  105.     [[newTextView window] setTitle:"SourceCode"/*,++i*/];  // replace "Untitled"     
  106.     // return self;
  107.     return newTextView;
  108. }
  109.  
  110. // appAcceptsAnotherFile is an application delegate method which 
  111. // returns whether it is OK for the application to try to open more files
  112. // with the appOpenFile:type: method. TextLab can indeed open multiple
  113. // windows, so we return YES.
  114.  
  115. -(BOOL) appAcceptsAnotherFile:sender
  116. {
  117.   return (YES);
  118. }
  119.  
  120.  
  121. // appOpenFile:type: is called to open the specified file. It is normally
  122. // called by the Application object in response to open requests from the
  123. // Workspace. Here we also route the open requests from the OpenPanel
  124. // to this method (see openRequest:).
  125.  
  126. -(int) appOpenFile:(char *)fileName type:(char *)fileType
  127. {
  128.    return [self openFile:fileName];  
  129. }
  130.  
  131. // openRequest: opens a new file. It puts up a open panel, and, if the user
  132. // doesn't cancel, it reads the specified archive file. If the selected file
  133. // is not a proper archive file, then openRequest: will complain.
  134.  
  135. - openRequest:sender
  136. {
  137.     const char *fileName;
  138.     const char *const types[] = {[stringSet valueForStringKey:"extension"],
  139.                       "tl", NULL};
  140.  
  141.     if ([openReq runModalForTypes:types] && (fileName = [openReq filename])) {
  142.     [self openFile:fileName];
  143.     }
  144.     else
  145.     [self showError:[stringSet valueForStringKey:"errorOnOpenRequest"]];
  146.     return self;
  147. }
  148.  
  149. -(int) openFile:(const char *)fileName
  150. {
  151.    id win;
  152.    NXTypedStream *typedStream;
  153.    
  154.     if(!(typedStream = NXOpenTypedStreamForFile(fileName,NX_READONLY))){
  155.     [self showError:[stringSet valueForStringKey:"errorOnOpen"]];
  156.     return NO;
  157.     }
  158.     else {
  159.     win = NXReadObject(typedStream);
  160.     NXCloseTypedStream(typedStream);
  161.     [win setTitle:fileName];
  162.     [win setDelegate:self];
  163.         // [[win display] makeKeyAndOrderFront:self];
  164.     [win display];
  165.     [win makeKeyAndOrderFront:self];
  166.     [self windowDidBecomeKey:win];  // don't know why, but need this
  167.                                     // to get delegate notification
  168.     [self saveRequest:self];
  169.     return YES;
  170.     } 
  171. }
  172.  
  173.  
  174. // saveRequest: saves the current window under its default name (found in
  175. // the title bar). Note that if the title bar is empty or the default title
  176. // is "SourceCode" then saveRequest: will put up a save panel, giving the user
  177. // a chance to specify a real title.
  178.  
  179. - saveRequest:sender
  180. {
  181.     const char *fileName;
  182.     const char *const types[2] = {[stringSet valueForStringKey:"extension"],
  183.                       NULL};
  184.     
  185.     id curWin = [NXApp mainWindow];
  186.     [saveReq setRequiredFileType:types[0]];
  187.     
  188.     if (curWin == nil) 
  189.     [self showError:[stringSet valueForStringKey:"errorOnSaveRequest"]];
  190.     else {
  191.     // Check to see if the current window is titled and the title is not
  192.     // "Untitled". If so, save the file, else put up a save panel...
  193.     fileName = [curWin title];
  194.     
  195.     printf("setString returns: %s\n", [stringSet valueForStringKey:"SourceCode"]);
  196.     printf("setString returns: %s\n", [stringSet valueForStringKey:"Diagram"]);
  197.     
  198.         if (strcmp (fileName, [stringSet valueForStringKey:"Diagram"])) {
  199.        if (strcmp (fileName, [stringSet valueForStringKey:"SourceCode"]))
  200.           [self saveWindow:curWin inPath:fileName];
  201.        else 
  202.           [self saveInRequest:sender];
  203.            }
  204.         else
  205.            [self showError:[stringSet valueForStringKey:"errorOnDiagramSave"]];
  206.     }
  207.     [curWin setDocEdited:NO];
  208.     return self;
  209. }
  210.  
  211. // saveInRequest: gives the user a chance to save the current window
  212. // under a new name. 
  213.  
  214. - saveInRequest:sender
  215. {
  216.     const char *fileName;
  217.     const char *const types[2] = {[stringSet valueForStringKey:"extension"],
  218.                       NULL};
  219.     id        curWin;
  220.     
  221.     curWin = [NXApp mainWindow];
  222.     [saveReq setRequiredFileType:types[0]];
  223.  
  224.     if (curWin == nil) 
  225.     [self showError:[stringSet valueForStringKey:"errorOnSaveIn"]];
  226.     else {
  227.         fileName = [curWin title];
  228.     if (strcmp (fileName, [stringSet valueForStringKey:"Diagram"])){ 
  229.          // Get a file name from the user; use title of the window as default.
  230.      if (([saveReq runModalForDirectory:[stringSet valueForStringKey:"dot"]
  231.                               file:[curWin title]]) &&
  232.           (fileName = [saveReq filename])) 
  233.         [self saveWindow:curWin inPath:fileName];}
  234.          else {
  235.        [self showError:[stringSet valueForStringKey:"errorOnDiagramSave"]];
  236. }
  237. }
  238.     [curWin setDocEdited:NO];
  239.     return self;
  240. }
  241.  
  242.  
  243. // saveWindow writes a window out the archive file whose name is specified
  244. // by the second argument. The title of the current window is also set 
  245. // accordingly. 
  246.  
  247. - saveWindow:(id)win inPath:(const char *)name
  248. {    
  249.     NXTypedStream *typedStream;
  250.     
  251.     [win setTitle:name];
  252.     typedStream = NXOpenTypedStreamForFile(name,NX_WRITEONLY);
  253.     NXWriteRootObject(typedStream,win);
  254.     NXCloseTypedStream(typedStream);
  255.     return self;
  256. }
  257.  
  258. // Printing is rather simple; just send printPSCode: to the text view
  259. // you wish to print. The print panel will automatically pop up and unless
  260. // the user cancels the printout the text view will be printed.
  261.  
  262. - printRequest:sender
  263. {
  264.     id curText = [[[NXApp mainWindow] contentView] docView];
  265.  
  266.     if (curText == nil) [self showError:[stringSet
  267.                         valueForStringKey:"errorOnPrintRequest"]];
  268.     else {
  269.     [[[NXApp printInfo] setHorizCentered:NO] setVertCentered:NO];
  270.         [curText printPSCode:self];
  271.     }
  272.     return self;
  273. }
  274.  
  275. // closeRequest closes the current window by simulating a click on the
  276. // closebutton. A check should probably be added to give the user the 
  277. // option of saving the window before closing
  278.  
  279. - closeRequest:sender
  280. {
  281.    id curWin = [NXApp mainWindow];
  282.    
  283.    if ([curWin isDocEdited])
  284.    [self saveRequest:self];
  285.    else
  286.    [[NXApp mainWindow] performClose:sender];
  287.    return self;
  288. }
  289.  
  290. -showActionDiagram:sender
  291. {
  292.     [self writeSourceToTmp];
  293.     //  [theDiagrammer formatDiagram];
  294.     system("adroff -g tmpAdroffSource tmpAdroffDiagram");
  295.     [self readDiagToWindow2];
  296.     return self;
  297. }
  298.  
  299. -writeSourceToTmp
  300. {
  301.     NXStream *stream;
  302.     id sourceText;
  303.     const char *fileName = "tmpAdroffSource";
  304.     
  305.     system("cp  /dev/null     tmpAdroffSource");
  306.     sourceText = [sourceView docView];
  307.     stream = NXMapFile(fileName, NX_WRITEONLY);       
  308.     NXSeek(stream,0, NX_FROMSTART);  
  309.     [sourceText writeText:stream];
  310.     NXFlush(stream);
  311.     NXSaveToFile(stream,fileName);
  312.     NXCloseMemory(stream,NX_FREEBUFFER);
  313.     return self;
  314. }
  315.  
  316. - readDiagToWindow2
  317. {
  318.     NXStream *stream;
  319.     id               diagText;
  320.    
  321.     const char *fileName = "tmpAdroffDiagram";
  322.  
  323.     diagText = [diagramView docView];
  324.     stream = NXMapFile(fileName, NX_READONLY);       
  325.     NXSeek(stream,0, NX_FROMSTART);  
  326.     [diagText readText:stream];
  327.     // NXFlush(stream);
  328.     // NXSaveToFile(stream,fileName);
  329.     NXCloseMemory(stream,NX_FREEBUFFER);
  330.     return self;
  331. }
  332.  
  333. /*
  334.  * Delegate method for the document Text object. We use this method
  335.  * to detect when the text in the window is modified.
  336.  */
  337. - textDidGetKeys:textObject isEmpty:(BOOL)flag 
  338. {
  339.     id curWin = [NXApp mainWindow];
  340.     // id curWin = [NXApp keyWindow];
  341.     //  if (![[sourceView window] isDocEdited]) 
  342.     if (![curWin isDocEdited]) 
  343.     {
  344.         [curWin setDocEdited:YES];
  345.     }
  346.     return NO;
  347. }
  348.  
  349. - windowDidBecomeKey:sender
  350. {
  351.      id sourceText;
  352.      sourceView = [sender contentView];
  353.      sourceText = [[sourceView docView] setDelegate:self];
  354.      // [sourceText setSel:(int)0 :(int)0];
  355.      [sender becomeMainWindow];
  356.      return self;
  357. }
  358.  
  359. // Called just before the window closes.
  360. - windowWillClose:sender
  361. {
  362.    id curWin = [NXApp mainWindow];
  363.    
  364.    if ([curWin isDocEdited]){
  365.       [self saveRequest:self]; 
  366.       }
  367.    return self;
  368. }
  369.  
  370. @end
  371.